package com.tenebrous.jestic.service.framwork.meber.organ;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.tenebrous.jestic.entity.TreeSerializable;
import com.tenebrous.jestic.entity.framwork.meber.organ.OrgOrganize;
import com.tenebrous.jestic.entity.framwork.meber.organ.OrgUser;
import com.tenebrous.jestic.entity.framwork.system.MetaDictionary;
import com.tenebrous.jestic.entity.framwork.system.SysLogModify;
import com.tenebrous.jestic.mapper.idao.framwork.meber.organ.OrgOrganizeMapper;
import com.tenebrous.jestic.mapper.idao.framwork.meber.organ.OrgUserAccountMapper;
import com.tenebrous.jestic.mapper.idao.framwork.meber.organ.OrgUserMapper;
import com.tenebrous.jestic.mapper.idao.framwork.system.MetaDictionaryMapper;
import com.tenebrous.jestic.mapper.idao.framwork.system.SysLogModifyMapper;
import com.tenebrous.jestic.service.SuperService;
import com.rain.ops.sdk.dto.ApiResult;
import com.rain.ops.sdk.utils.UUIDUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

@Service
public class OrgOrganizeService extends SuperService<OrgOrganize> {

    @Autowired
    private OrgOrganizeMapper mapper;

    @Autowired
    private OrgUserMapper userMapper;

    @Autowired
    private SysLogModifyMapper modifyLogMapper;

    @Autowired
    private MetaDictionaryMapper dictionaryMapper;

    @Autowired
    private OrgUserAccountMapper userAccountMapper;

    @Override
    @Autowired
    protected void setSuperMapper() {
        super.setSuperMapper(this.mapper);
    }

    public OrgOrganize getById(String id) {
        return this.mapper.selectById(id);
    }

    public List<TreeSerializable> queryTree(String companyid) {
        return this.queryTree(companyid, null, false);
    }

    public List<TreeSerializable> queryTree(String companyid, String[] otypes) {
        return this.queryTree(companyid, otypes, false);
    }

    public List<TreeSerializable> queryTree(String companyid, String[] otypes, boolean extended) {
        List<String> companyids = new ArrayList<>();
        if (StringUtils.isNotBlank(companyid)) {
            companyids.add(companyid);
        }
        return this.queryTree(companyids.toArray(new String[companyids.size()]), otypes, extended);
    }

    public List<TreeSerializable> queryDtree(String companyid, String[] otypes, boolean extended) {
        List<TreeSerializable> result = new ArrayList<>();
        List<OrgOrganize> mlist = this.mapper.selectByCondition(new String[]{companyid}, null, null, otypes);
        for (OrgOrganize ditem : mlist) {
            if (extended) {
                ditem.setRegularcnt(this.userMapper.selectRegularEmployCount(null, ditem.getId()));
            }
            if (!"0".equals(ditem.getPid())) {
                result.add(ditem);
            }
        }
        return this.buildTree(result, companyid);
    }

    public List<TreeSerializable> queryTree(String[] companyids, String[] otypes, boolean extended) {
        List<TreeSerializable> result = new ArrayList<>();
        List<OrgOrganize> mlist = this.mapper.selectByCondition(companyids, null, null, otypes);
        result.addAll(mlist);
        if (extended) {
            for (OrgOrganize ditem : mlist) {
                ditem.setRegularcnt(this.userMapper.selectRegularEmployCount(null, ditem.getId()));
            }
        }
        return this.buildTree(result, "0");
    }

    public List<OrgOrganize> queryOrgByOgrade(String ograde) {
        return this.mapper.queryOrgByOgrade(ograde);
    }

    public List<OrgOrganize> queryList(String[] companyids) {
        return this.queryList(companyids, null);
    }

    public List<OrgOrganize> queryList(String[] companyids, String[] otypes) {
        return this.mapper.selectByCondition(companyids, null, null, otypes);
    }

    public PageInfo<OrgOrganize> queryPagingList(Integer pageIndex, Integer pageSize, String companyid, String pid, String name) {
        List<String> companyids = new ArrayList<>();
        if (StringUtils.isNotBlank(companyid)) {
            companyids.add(companyid);
        }
        PageInfo pageInfo = PageHelper.startPage(pageIndex, pageSize).doSelectPageInfo(() -> this.mapper.selectByCondition(companyids.toArray(new String[companyids.size()]), pid, name, null));
        List<OrgOrganize> list = pageInfo.getList();
        for (OrgOrganize ditem : list) {
            Integer cnt = this.userMapper.selectRegularEmployCount(null, ditem.getId());
            ditem.setRegularcnt(cnt);
        }
        return pageInfo;
    }

    /**
     * 保存或修改
     *
     * @param item
     * @return
     */
    @Transactional
    public OrgOrganize update(OrgOrganize item, OrgUser ouser) {
        Date dt = new Date();
        if (StringUtils.isNotBlank(item.getId())) {//修改
            item.setUpdateDate(dt);
            item.setUpdateUserid(ouser != null ? ouser.getId() : null);
            if (StringUtils.isNotBlank(item.getPid())) {
                OrgOrganize pitem = this.mapper.selectByPrimaryKey(item.getPid());
                if (pitem != null) {
                    item.setCompanyid(pitem.getCompanyid());
                    Integer olevel = pitem.getOlevel();
                    if (olevel != null) {
                        item.setOlevel(++olevel);
                    }
                }
            }
            if ("OC".equalsIgnoreCase(item.getOtype())) {
                item.setCompanyid(item.getId());
            }
            if (StringUtils.isNotBlank(item.getOgrade())) {
                MetaDictionary dic = dictionaryMapper.getByCode(item.getOgrade());
                if (dic != null) {
                }
                item.setOgradename(dic.getName());
            }
            this.mapper.updateByPrimaryKeySelective(item);

            String safter = String.format("修改后：%s；", item.getName());
            String afterJosn = JSON.toJSONString(item);
            SysLogModify mlog = new SysLogModify();
            mlog.setId(UUIDUtils.randomUUID());
            mlog.setSclass(OrgOrganize.class.getName());
            mlog.setSafter(afterJosn);
            mlog.setDafter(safter);
            mlog.setSstamp(dt.getTime());
            mlog.setBatch("ORGANIZE");
            mlog.setOtype("编辑组织");
            mlog.setMdesc(safter);
            mlog.setCreateDate(dt);
            mlog.setCreateUserid(ouser != null ? ouser.getId() : null);
            this.modifyLogMapper.insertSelective(mlog);
        } else {//新增
            item.setId(UUIDUtils.randomUUID());
            item.setSort(dt.getTime());
            item.setCreateDate(dt);
            item.setCreateUserid(ouser != null ? ouser.getId() : null);
            item.setOlevel(1);
            if (StringUtils.isNotBlank(item.getPid())) {
                OrgOrganize pitem = this.mapper.selectByPrimaryKey(item.getPid());
                if (pitem != null) {
                    item.setCompanyid(pitem.getCompanyid());
                    Integer olevel = pitem.getOlevel();
                    if (olevel != null) {
                        item.setOlevel(++olevel);
                    }
                }
            }
            if ("OC".equalsIgnoreCase(item.getOtype())) {
                item.setCompanyid(item.getId());
            }
            if (StringUtils.isNotBlank(item.getOgrade())) {
                MetaDictionary dic = dictionaryMapper.getByCode(item.getOgrade());
                if (dic != null) {
                }
                item.setOgradename(dic.getName());
            }
            this.mapper.insertSelective(item);

            String safter = String.format("新增：%s；", item.getName());
            String afterJosn = JSON.toJSONString(item);
            SysLogModify mlog = new SysLogModify();
            mlog.setId(UUIDUtils.randomUUID());
            mlog.setSclass(OrgOrganize.class.getName());
            mlog.setSafter(afterJosn);
            mlog.setDafter(safter);
            mlog.setSstamp(dt.getTime());
            mlog.setBatch("ORGANIZE");
            mlog.setOtype("新增组织");
            mlog.setMdesc(safter);
            mlog.setCreateDate(dt);
            mlog.setCreateUserid(ouser != null ? ouser.getId() : null);
            this.modifyLogMapper.insertSelective(mlog);
        }
        return item;
    }

    /**
     * 删除指定记录及其下级所有组织信息
     *
     * @param id
     * @return
     */
    @Transactional
    public int deleteTree(String id) {
        int i = 0;
        List<String> ids = new ArrayList<>();
        ids.add(id);
        this.getIds(ids, id);
        for (String item : ids) {
            i += this.mapper.deleteByPrimaryKey(item);
        }
        return i;
    }

    @Transactional
    public int deleteTree(String[] ids) {
        int i = 0;
        for (String id : ids) {
            i += this.deleteTree(id);
        }
        return i;
    }

    @Transactional
    public void deleteall(String code, String did) {
        if (StringUtils.isNotBlank(did)) {
            this.mapper.deleteByPrimaryKey(did);
            List<OrgUser> list = userMapper.queryListByDepartmentid(did);
            for (OrgUser it : list) {
                userAccountMapper.deleteByUserid(it.getId());
            }
            userMapper.deleteByDepartid(did);
        }
        if (StringUtils.isNotBlank(code)) {
            List<OrgOrganize> list = mapper.queryOrgByOgrade(code);
            for (OrgOrganize it : list) {
                List<OrgUser> list1 = userMapper.queryListByDepartmentid(it.getId());
                for (OrgUser it1 : list1) {
                    userAccountMapper.deleteByUserid(it1.getId());
                }
                userMapper.deleteByDepartid(it.getCompanyid());
            }
            this.mapper.deleteByOgrade(code);
        }
    }

    /**
     * 向上移动
     *
     * @param id
     * @return
     */
    @Transactional
    public ApiResult up(String id) {
        OrgOrganize item = this.mapper.selectByPrimaryKey(id);
        if (item != null) {
            OrgOrganize cd = new OrgOrganize();
            cd.setPid(item.getPid());
            List<OrgOrganize> list = this.mapper.select(cd);
            list.sort(Comparator.comparing(OrgOrganize::getSort).reversed());
            OrgOrganize titem = list.stream().filter(o -> o.getSort() < item.getSort()).findFirst().orElse(null);
            if (titem != null) {
                item.setSort(item.getSort() + titem.getSort());
                titem.setSort(item.getSort() - titem.getSort());
                item.setSort(item.getSort() - titem.getSort());

                this.mapper.updateByPrimaryKeySelective(item);
                this.mapper.updateByPrimaryKeySelective(titem);
                return new ApiResult(200, "上移成功。");
            } else {
                return new ApiResult(999, "无法上移，已是最前一条记录。");
            }
        }
        return new ApiResult(999, "上移失败，指定部门不存在。");
    }

    /**
     * 向下移动
     *
     * @param id
     * @return
     */
    @Transactional
    public ApiResult down(String id) {
        OrgOrganize item = this.mapper.selectByPrimaryKey(id);
        if (item != null) {
            OrgOrganize cd = new OrgOrganize();
            cd.setPid(item.getPid());
            List<OrgOrganize> list = this.mapper.select(cd);
            list.sort(Comparator.comparing(OrgOrganize::getSort));
            OrgOrganize titem = list.stream().filter(o -> o.getSort() > item.getSort()).findFirst().orElse(null);
            if (titem != null) {
                item.setSort(item.getSort() + titem.getSort());
                titem.setSort(item.getSort() - titem.getSort());
                item.setSort(item.getSort() - titem.getSort());

                this.mapper.updateByPrimaryKeySelective(item);
                this.mapper.updateByPrimaryKeySelective(titem);
                return new ApiResult(200, "下移成功。");
            } else {
                return new ApiResult(999, "无法下移，已是最后一条记录。");
            }
        }
        return new ApiResult(999, "下移失败，指定部门不存在。");
    }

    /**
     * 移动组织
     *
     * @param id               被移动的组织ID
     * @param targetOrganizeid 移动后的上级组织
     * @return
     */
    @Transactional
    public ApiResult move(String id, String targetOrganizeid, SysLogModify mlog, OrgUser ouser) {
        Date dt = new Date();
        OrgOrganize sitem = this.selectByPrimaryKey(id);
        OrgOrganize titem = this.selectByPrimaryKey(targetOrganizeid);
        if (sitem != null && titem != null) {
            String beforJosn = JSON.toJSONString(sitem);
            List<String> prepath = new ArrayList<>();
            List<String> nexpath = new ArrayList<>();
            this.getPrePath(prepath, sitem.getId());
            this.getPrePath(nexpath, targetOrganizeid);
            String sbefor = String.format("变更前：%s；", StringUtils.join(prepath, "/"));
            String safter = String.format("变更后：%s/%s；", StringUtils.join(nexpath, "/"), sitem.getName());

            sitem.setCompanyid(titem.getCompanyid());
            sitem.setPid(targetOrganizeid);
            sitem.setUpdateDate(dt);
            sitem.setUpdateUserid(ouser != null ? ouser.getId() : null);
            Integer tlevel = titem.getOlevel();
            if (tlevel != null) {
                sitem.setOlevel(++tlevel);
            }
            this.mapper.updateByPrimaryKeySelective(sitem);
            String afterJosn = JSON.toJSONString(sitem);

            mlog.setId(UUIDUtils.randomUUID());
            mlog.setSclass(OrgOrganize.class.getName());
            mlog.setSbefor(beforJosn);
            mlog.setSafter(afterJosn);
            mlog.setDbefor(sbefor);
            mlog.setDafter(safter);
            mlog.setSstamp(dt.getTime());
            mlog.setBatch("ORGANIZE");
            mlog.setOtype("组织移动");
            mlog.setMdesc(sbefor + safter);
            mlog.setCreateDate(dt);
            mlog.setCreateUserid(ouser != null ? ouser.getId() : null);
            this.modifyLogMapper.insertSelective(mlog);

            return new ApiResult(200, "移动成功。");
        } else {
            return new ApiResult(999, "移动失败，未找到被移动组织信息。");
        }
    }

    /**
     * 拆分组织
     *
     * @param id       被拆分的组织ID
     * @param retained 是否保留原组织
     * @param items    拆分后的组织
     * @param ouser
     * @return
     */
    @Transactional
    public ApiResult split(String id, Boolean retained, String items, SysLogModify mlog, OrgUser ouser) {
        Date dt = new Date();
        List<OrgUser> oulist = this.userMapper.selectByCondition(null, id, null, "在职", 1, null, null, null, null, null, null);
        if (oulist.size() == 0) {
            OrgOrganize sitem = this.mapper.selectByPrimaryKey(id);
            if (sitem != null) {
                List<String> prepath = new ArrayList<>();
                List<String> nexpath = new ArrayList<>();
                this.getPrePath(prepath, sitem.getId());
                String beforJosn = JSON.toJSONString(sitem);
                List<OrgOrganize> ditems = JSON.parseArray(items, OrgOrganize.class);
                for (OrgOrganize item : ditems) {
                    item.setId(UUIDUtils.randomUUID());
                    item.setCreateUserid(ouser != null ? ouser.getId() : null);
                    item.setCreateDate(dt);
                    item.setOtype("OD");
                    if (StringUtils.isNotBlank(item.getPid())) {
                        OrgOrganize pitem = this.mapper.selectByPrimaryKey(item.getPid());
                        if (pitem != null) {
                            item.setCompanyid(pitem.getCompanyid());
                        }
                    }
                    this.mapper.insertSelective(item);

                    List<String> xpath = new ArrayList<>();
                    this.getPrePath(xpath, item.getId());
                    nexpath.add(StringUtils.join(xpath, "/"));
                }
                if (!retained) {
                    this.mapper.deleteByPrimaryKey(id);
                }
                String afterJosn = JSON.toJSONString(ditems);

                String sbefor = String.format("变更前：%s。", StringUtils.join(prepath, "/"));
                String safter = String.format("变更后：%s。", "新增，" + StringUtils.join(nexpath, "，") + (retained ? "" : " 删除，" + StringUtils.join(prepath, "/")));

                mlog.setId(UUIDUtils.randomUUID());
                mlog.setSclass(OrgOrganize.class.getName());
                mlog.setSbefor(beforJosn);
                mlog.setSafter(afterJosn);
                mlog.setDbefor(sbefor);
                mlog.setDafter(safter);
                mlog.setSstamp(dt.getTime());
                mlog.setBatch("ORGANIZE");
                mlog.setOtype("组织拆分");
                mlog.setMdesc(sbefor + safter);
                mlog.setCreateDate(dt);
                mlog.setCreateUserid(ouser != null ? ouser.getId() : null);
                this.modifyLogMapper.insertSelective(mlog);

                return new ApiResult(200, "拆分成功。");
            } else {
                return new ApiResult(999, "拆分失败，未找到被拆分组织信息。");
            }
        } else {
            return new ApiResult(999, "拆分失败，被拆分组织中存在人员信息。");
        }
    }

    /**
     * 合并组织
     *
     * @param ids     被合并的组织ID
     * @param newitem 合并后的部门
     * @return
     */
    @Transactional
    public ApiResult meger(String[] ids, OrgOrganize newitem, SysLogModify mlog, OrgUser ouser) {
        Date dt = new Date();
        List<String> prepath = new ArrayList<>();
        List<String> nexpath = new ArrayList<>();
        List<OrgOrganize> olist = new ArrayList<>();
        List<OrgUser> oulist = this.userMapper.selectUserByDepartmentids(ids, "在职");
        if (oulist.size() == 0) {
            for (String id : ids) {
                OrgOrganize oitem = this.mapper.selectByPrimaryKey(id);
                if (oitem != null) {
                    olist.add(oitem);
                    List<String> xpath = new ArrayList<>();
                    this.getPrePath(xpath, id);
                    prepath.add(StringUtils.join(xpath, "/"));
                    this.mapper.deleteByPrimaryKey(id);
                }
            }
            newitem.setId(UUIDUtils.randomUUID());
            newitem.setCreateUserid(ouser != null ? ouser.getId() : null);
            newitem.setCreateDate(dt);
            newitem.setOtype("OD");
            if (StringUtils.isNotBlank(newitem.getPid())) {
                OrgOrganize pitem = this.mapper.selectByPrimaryKey(newitem.getPid());
                if (pitem != null) {
                    newitem.setCompanyid(pitem.getCompanyid());
                }
            }
            this.mapper.insertSelective(newitem);
            this.getPrePath(nexpath, newitem.getId());

            String sbefor = String.format("变更前：%s。", StringUtils.join(prepath, "，"));
            String safter = String.format("变更后：%s。", StringUtils.join(nexpath, "/"));

            mlog.setSclass(OrgOrganize.class.getName());
            mlog.setSbefor(JSON.toJSONString(olist));
            mlog.setSafter(JSON.toJSONString(newitem));
            mlog.setDbefor(sbefor);
            mlog.setDafter(safter);
            mlog.setId(UUIDUtils.randomUUID());
            mlog.setSstamp(dt.getTime());
            mlog.setBatch("ORGANIZE");
            mlog.setOtype("组织合并");
            mlog.setMdesc(sbefor + safter);
            mlog.setCreateDate(dt);
            mlog.setCreateUserid(ouser != null ? ouser.getId() : null);
            this.modifyLogMapper.insertSelective(mlog);

            return new ApiResult(200, "合并成功。");
        } else {
            return new ApiResult(999, "合并失败，被合并组织中存在人员信息。");
        }
    }

    /**
     * 组织更名
     *
     * @param id      被更名的组织ID
     * @param newitem 更名后的组织信息
     * @return
     */
    @Transactional
    public ApiResult rename(String id, OrgOrganize newitem, SysLogModify mlog, OrgUser ouser) {
        Date dt = new Date();
        OrgOrganize sitem = this.mapper.selectByPrimaryKey(id);
        if (sitem != null) {
            String beforJosn = JSON.toJSONString(sitem);
            String sbefor = String.format("变更前：%s（%s）。", sitem.getName(), sitem.getFullname());

            sitem.setName(newitem.getName());
            sitem.setFullname(newitem.getFullname());
            sitem.setRemark(newitem.getRemark());
            sitem.setUpdateDate(dt);
            sitem.setUpdateUserid(ouser != null ? ouser.getId() : null);
            this.mapper.updateByPrimaryKeySelective(sitem);

            String afterJosn = JSON.toJSONString(sitem);
            String safter = String.format("变更后：%s（%s）。", sitem.getName(), sitem.getFullname());

            mlog.setSclass(OrgOrganize.class.getName());
            mlog.setId(UUIDUtils.randomUUID());
            mlog.setSbefor(beforJosn);
            mlog.setSafter(afterJosn);
            mlog.setDbefor(sbefor);
            mlog.setDafter(safter);
            mlog.setSstamp(dt.getTime());
            mlog.setBatch("ORGANIZE");
            mlog.setOtype("组织更名");
            mlog.setMdesc(sbefor + safter);
            mlog.setCreateDate(dt);
            mlog.setCreateUserid(ouser != null ? ouser.getId() : null);
            this.modifyLogMapper.insertSelective(mlog);

            return new ApiResult(200, "更名成功。");
        } else {
            return new ApiResult(999, "更名失败，未找到被更名组织信息。");
        }
    }

    /**
     * 撤销组织
     *
     * @param id    被撤销的组织ID
     * @param mlog
     * @param ouser
     * @return
     */
    @Transactional
    public ApiResult cancel(String id, SysLogModify mlog, OrgUser ouser) {
        Date dt = new Date();
        OrgOrganize sitem = this.mapper.selectByPrimaryKey(id);
        if (sitem != null) {
            String beforJosn = JSON.toJSONString(sitem);
            String sbefor = String.format("撤销前：%s（%s）。", sitem.getName(), sitem.getFullname());

            this.mapper.deleteByPrimaryKey(id);

            mlog.setSclass(OrgOrganize.class.getName());
            mlog.setId(UUIDUtils.randomUUID());
            mlog.setSbefor(beforJosn);
            mlog.setDbefor(sbefor);
            mlog.setSstamp(dt.getTime());
            mlog.setBatch("ORGANIZE");
            mlog.setOtype("组织撤销");
            mlog.setMdesc(sbefor);
            mlog.setCreateDate(dt);
            mlog.setCreateUserid(ouser != null ? ouser.getId() : null);
            this.modifyLogMapper.insertSelective(mlog);

            return new ApiResult(200, "撤销成功。");
        } else {
            return new ApiResult(999, "撤销失败，未找到被撤销的组织信息。");
        }
    }

    /**
     * 查看指定记录的所有下级ID
     *
     * @param ids
     * @param pid
     */
    public void getIds(List<String> ids, String pid) {
        List<OrgOrganize> list = this.mapper.selectByCondition(null, pid, null, null);
        //遍历二级分类的对象，把二级分类的id加入到要删除的集合中
        for (OrgOrganize item : list) {
            String id = item.getId();
            ids.add(id);
            //把二级分类的每一个ID，查询它下面的子节点
            this.getIds(ids, id);
        }
    }

    public Object queryChartTree(String[] companyids) {
        List<TreeSerializable> result = new ArrayList<>();
        List<OrgOrganize> mlist = this.mapper.queryChartList(companyids);
        for (OrgOrganize ditem : mlist) {
            result.add(ditem);
        }
        return this.buildTree(result, "0");
    }

    public void getPrePath(List<String> paths, String id) {
        OrgOrganize item = this.mapper.selectByPrimaryKey(id);
        paths.add(0, item.getName());
        String pid = item.getPid();
        if (StringUtils.isNotBlank(pid) && !pid.equals("0")) {
            this.getPrePath(paths, pid);
        }
    }
}
